﻿using System.Collections.Generic;

namespace Raven
{
    public class ProjectileSlug : RavenProjectile
    {
        //when this projectile hits something it's trajectory is rendered
        //for this amount of time
        private Fix _timeShotIsVisible;

        public ProjectileSlug(RavenBot shooter, Vector2 target) :
            base(EntityType.Slug, target, shooter.GetWorld(), shooter.ID(), shooter.Pos(),
                shooter.Facing(), Constants.Slug_Damage, Constants.Slug_BRadius, Constants.Slug_MaxSpeed,
                Constants.Slug_Mass, Constants.Slug_MaxForce)
        {
            _timeShotIsVisible = Constants.Slug_Persistance;
        }

        public override void Update()
        {
            if (!HasImpacted())
            {
                //calculate the steering force
                Vector2 DesiredVelocity = (_target - Pos()).normalized * MaxSpeed();

                Vector2 sf = DesiredVelocity - Velocity();

                //update the position
                Vector2 accel = sf / _mass;

                _velocity += accel;

                //make sure the slug does not exceed maximum velocity
                _velocity.Truncate(_maxSpeed);

                //update the position
                _position += _velocity;

                TestForImpact();
            }
            else if (!isVisibleToPlayer())
            {
                _dead = true;
            }
            base.Update();
        }

        //returns true if the shot is still to be rendered
        private bool isVisibleToPlayer()
        {
            return _world.GetTimer().currentTime < _timeOfCreation + _timeShotIsVisible;
        }

        //----------------------------------- TestForImpact ---------------------------
        private void TestForImpact()
        {
            // a rail gun slug travels VERY fast. It only gets the chance to update once 
            _impacted = true;

            //first find the closest wall that this ray intersects with. Then we
            //can test against all entities within this range.
            Fix DistToClosestImpact = 0;
            WallIntersectionTests.FindClosestPointOfIntersectionWithWalls(_origin,
                _position,
                ref DistToClosestImpact,
                ref _impactPoint,
                _world.GetMap().GetWalls());

            //test to see if the ray between the current position of the slug and 
            //the start position intersects with any bots.
            LinkedList<RavenBot> hits = GetListOfIntersectingBots(_origin, _impactPoint);

            //if no bots hit just return;
            if (hits.Count == 0)
                return;

            //give some damage to the hit bots
            foreach (var it in hits)
            {
                //send a message to the bot to let it know it's been hit, and who the
                //shot came from
                _world.Dispatcher.DispatchMsg(Constants.SEND_MSG_IMMEDIATELY,
                    _shooterID,
                    it.ID(),
                    MessageType.Msg_TakeThatMF,
                    _damageInflicted);
            }
        }
    }
}